package com.jerry.service.Impl;

import com.jerry.DTO.FileChunkDTO;
import com.jerry.config.ChunkConfig;
import com.jerry.service.FileService;
import com.jerry.utils.Md5Util;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@Service
public class FileServiceImpl implements FileService {
    private final ChunkConfig chunkConfig;
    private final ReentrantReadWriteLock reentrantReadWriteLock;

    public FileServiceImpl(ChunkConfig chunkConfig, ReentrantReadWriteLock reentrantReadWriteLock) {
        this.chunkConfig = chunkConfig;
        this.reentrantReadWriteLock = reentrantReadWriteLock;
    }

    @Override
    public byte[] read(String filename, String extension, String bucketName, Integer chunkNo) {
        String chunkPath = buildChunkPath(bucketName, filename, extension, chunkNo);
        try{
            reentrantReadWriteLock.readLock().lock();
            return Files.readAllBytes(Paths.get(chunkPath));
        }catch (Exception e){
            throw new RuntimeException("获取文件失败");
        }finally {
            reentrantReadWriteLock.readLock().unlock();
        }
    }

    @Override
    public String write(FileChunkDTO fileChunkDTO) {
        String bucketName = fileChunkDTO.getBucketName();
        Integer chunkNo = fileChunkDTO.getChunkNo();
        Integer chunksize = fileChunkDTO.getChunksize();
        String extension = fileChunkDTO.getExtension();
        String filename = fileChunkDTO.getFilename();
        byte[] bytes = fileChunkDTO.getBytes();
        String chunkPath = buildChunkPath(bucketName, filename, extension, chunkNo);
        File chunkfile = new File(chunkPath);
        try (FileOutputStream fileOutputStream = new FileOutputStream(chunkfile)) {
            reentrantReadWriteLock.writeLock().lock();
            if (chunkfile.getFreeSpace() < chunksize) {
                throw new RuntimeException("磁盘空间不足");
            }
            if (!chunkfile.exists()) {
                boolean create = chunkfile.createNewFile();
                if (!create) {
                    throw new RuntimeException("创建文件失败");
                }
            }
            fileOutputStream.write(bytes);
            return Md5Util.getMd5(bytes);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("写入文件失败");
        } finally {
            reentrantReadWriteLock.writeLock().unlock();
        }
    }

    @Override
    public void delete(String filename, String extension, String bucketName, Integer chunkNo) {
        String chunkPath = buildChunkPath(bucketName, filename, extension, chunkNo);
        try{
            reentrantReadWriteLock.writeLock().lock();
            Files.delete(Paths.get(chunkPath));
        }catch (IOException e){
            throw new RuntimeException("获取文件失败");
        }finally {
            reentrantReadWriteLock.writeLock().unlock();
        }
    }

    public String buildChunkPath(String buckeName, String filename, String extension, Integer chunkNo) {
        return String.format("%s/%s_%s_%s.%s", chunkConfig.getWorkSpace(), buckeName, filename, chunkNo, extension);
    }
}
